#include "HeightMap.h"

namespace PeanutQuest {
 
	//bool keys[256];
	bool active = TRUE;
	//bool fullscreen = TRUE;
	bool bRender = TRUE; 

	BYTE g_HeightMap[MAP_SIZE*MAP_SIZE];
	float scaleValue = 0.15f;
	LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

	void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap) {

		FILE *pFile = NULL;
		pFile = fopen(strName,"rb");
 
		if ( pFile == NULL ) {
			std::cout << "Cant find heightmap!";
			return;
		}

		fread( pHeightMap, 1, nSize, pFile );

		int result = ferror( pFile );

		if (result){
			std::cout << "Failed to get data!";
		}

		fclose(pFile);
	}

	HeightMap::HeightMap() : cg::Entity("HeightMap") {
	}

	HeightMap::~HeightMap() {
	}

	void HeightMap::makeMaterial() {
		
		GLfloat mat_emission[] = {1.0f,1.0f,1.0f,1.0f};
		GLfloat mat_ambient[] = {0.5f,0.5f,0.5f,1.0f};
		GLfloat mat_diffuse[] = {0.7f,0.7f,0.7f,1.0f};
		GLfloat mat_specular[] = {0.1f,1.0f,0.1f,1.0f};
		GLfloat mat_shininess[] = {100.0f};
		
		_materialDL = glGenLists(1);
		assert(_materialDL != 0);
		glNewList(_materialDL,GL_COMPILE);
			glMaterialfv(GL_FRONT,GL_EMISSION ,mat_emission);
			glMaterialfv(GL_FRONT,GL_AMBIENT,mat_ambient);
			glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);
			glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
			glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);
		glEndList();
	}

	int HeightMap::height(BYTE *pHeightMap, int X, int Y) {
		int x = X % MAP_SIZE;
		int y = Y % MAP_SIZE;
 
		if(!pHeightMap) return 0; 

		return pHeightMap[x + (y * MAP_SIZE)];
	}

	void HeightMap::setVertexColor(BYTE *pHeightMap, int x, int y) {
	
		if(!pHeightMap) return;
 
		float fColor = -0.15f + (height(pHeightMap, x, y) / 256.0f);
		glColor3f(0.0f, fColor, 0.0f);
	}

	void HeightMap::renderHeightMap(BYTE pHeightMap[]) {
		int X = 0, Y = 0;
		int x, y, z;
 
		if(!pHeightMap) return;

		if(bRender) {
			glBegin(GL_QUADS);
		}
		else {
			glBegin(GL_LINES);  
		}

		for ( X = 0; X < (MAP_SIZE-STEP_SIZE); X += STEP_SIZE )
		for ( Y = 0; Y < (MAP_SIZE-STEP_SIZE); Y += STEP_SIZE ) {
			x = X;                         
			y = height(pHeightMap, X, Y ); 
			z = Y;             

			setVertexColor(pHeightMap, x, z);
 
			glVertex3i(x, y, z);
 
			x = X;                                     
			y = height(pHeightMap, X, Y + STEP_SIZE ); 
			z = Y + STEP_SIZE ;                        
         
			setVertexColor(pHeightMap, x, z);
 
			glVertex3i(x, y, z);
 
			x = X + STEP_SIZE;
			y = height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE );
			z = Y + STEP_SIZE ;
 
			setVertexColor(pHeightMap, x, z);
         
			glVertex3i(x, y, z);
 
			x = X + STEP_SIZE;
			y = height(pHeightMap, X + STEP_SIZE, Y );
			z = Y;
 
			setVertexColor(pHeightMap, x, z);
 
			glVertex3i(x, y, z);
		}
		glEnd();

		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
	}

	void HeightMap::init() {

		makeMaterial();

		glShadeModel(GL_SMOOTH);
		glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
		glClearDepth(1.0f);
		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);
		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

		LoadRawFile("../../img/terrain.raw", MAP_SIZE * MAP_SIZE, g_HeightMap); 

	}

	void HeightMap::draw() {
		glPushMatrix();
		glCallList(_materialDL);

		glScalef(scaleValue, scaleValue * HEIGHT_RATIO, scaleValue);
		renderHeightMap(g_HeightMap);  

		glPopMatrix();	
	}

}

